package cn.com.chengmandian.bike.controller.rent;

import cn.com.chengmandian.bike.model.EbRefundInfo;
import cn.com.chengmandian.bike.service.IEbRefundInfoService;
import cn.com.chengmandian.bike.service.IEbRentComboService;
import cn.com.chengmandian.bike.service.IEbRentOrderService;
import cn.com.chengmandian.bike.utils.AliPayUtil;
import cn.com.chengmandian.bike.utils.WxPayUtil;
import cn.com.chengmandian.core.redis.cache.AgentCacheService;
import cn.com.chengmandian.core.redis.service.RedisService;
import cn.com.chengmandian.core.web.exceptions.BadResponseException;
import cn.com.chengmandian.core.web.pojo.AgentInfo;
import cn.com.chengmandian.core.web.pojo.AjaxResult;
import cn.com.chengmandian.core.web.utils.LocalMapUtil;
import cn.com.chengmandian.core.web.utils.SpringContextUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Api(tags = "租赁通知相关接口 - 微服务")
@RestController
@RequestMapping("/notify/rent")
public class RentNotifyController {

    @Autowired
    private IEbRentOrderService rentOrderService;
    @Autowired
    private AgentCacheService agentCacheService;
    @Autowired
    private IEbRefundInfoService refundInfoService;
    @Autowired
    private RedisService redisService;

    @ApiOperation("微信支付通知")
    @PostMapping("/wxpay/pay/{agentId}")
    public Map<String, String> wxpay(@PathVariable("agentId") String agentId, HttpServletRequest request){
        try {
            AgentInfo agentInfo = agentCacheService.getAgent(agentId);
            LocalMapUtil.setAgentInfo(agentInfo);

            JSONObject res = JSONObject.parseObject(WxPayUtil.parseNotify(request, agentInfo.getWxApiKey3(), agentInfo.getWxPlatformCertPath()));
            log.info("租赁套餐微信支付结果通知:{}", JSONObject.toJSONString(res));
            String payNo = res.getString("out_trade_no");
            String key = SpringContextUtil.getAppName().toUpperCase() + ":BIKE:RENT:PAY:NOTIFY:" + payNo;
            if (redisService.hasKey(key)) {
                log.info("租赁套餐微信支付结果通知:{} 订单重复响应", payNo);
                throw new BadResponseException("订单重复响应：" + payNo);
            }
            redisService.set(key, payNo, 60 * 10);
            rentOrderService.rentOrderPaySuccess(res.getString("out_trade_no"), res.getString("transaction_id"));
        } catch (Exception e) {
            log.error("租赁套餐微信支付结果通知异常", e);
        }
        Map<String, String> map = new HashMap<>(12);
        map.put("code", "SUCCESS");
        map.put("message", "成功");
        return map;
    }

    @ApiOperation("租赁订单续租微信支付通知")
    @PostMapping("/wxpay/pay/relet/{agentId}/{reletOrderId}")
    public Map<String, String> wxpayRelet(@PathVariable("agentId") String agentId, @PathVariable("reletOrderId") Integer reletOrderId, HttpServletRequest request){
        try {
            AgentInfo agentInfo = agentCacheService.getAgent(agentId);
            LocalMapUtil.setAgentInfo(agentInfo);

            JSONObject res = JSONObject.parseObject(WxPayUtil.parseNotify(request, agentInfo.getWxApiKey3(), agentInfo.getWxPlatformCertPath()));
            log.info("租赁订单续租租赁套餐微信支付结果通知:{}", JSONObject.toJSONString(res));
            String payNo = res.getString("out_trade_no");
            String key = SpringContextUtil.getAppName().toUpperCase() + ":BIKE:RENT:RELET:PAY:NOTIFY:" + payNo;
            if (redisService.hasKey(key)) {
                log.info("租赁订单续租租赁套餐微信支付结果通知:{} 订单重复响应", payNo);
                throw new BadResponseException("订单重复响应：" + payNo);
            }
            redisService.set(key, payNo, 60 * 10);
            rentOrderService.reletOrderSuccess(res.getString("out_trade_no"), res.getString("transaction_id"), reletOrderId);
        } catch (Exception e) {
            log.error("租赁订单续租租赁套餐微信支付结果通知异常", e);
        }
        Map<String, String> map = new HashMap<>(12);
        map.put("code", "SUCCESS");
        map.put("message", "成功");
        return map;
    }

    @ApiOperation("支付宝支付通知")
    @PostMapping("/ali/pay/{agentId}")
    public String aliPayNotify(@PathVariable("agentId") String agentId, HttpServletRequest request) {
        try {
            log.info("支付宝异步回调：{}", request.getRequestURI());
            log.info("支付宝异步回调：{}", request.getParameterMap());
            AgentInfo agentInfo = agentCacheService.getAgent(agentId);
            LocalMapUtil.setAgentInfo(agentInfo);
            Map<String, String> res = AliPayUtil.getRequestParam(request, agentInfo.getAliPayPublicCertPath());
            String payNo = res.get("out_trade_no");
            String key = SpringContextUtil.getAppName().toUpperCase() + ":BIKE:RENT:PAY:NOTIFY:" + payNo;
            if (redisService.hasKey(key)) {
                throw new BadResponseException("订单重复响应：" + payNo);
            }
            redisService.set(key, payNo, 60 * 10);
            if (res.size() > 0 && ("TRADE_FINISHED".equals(res.get("trade_status")) || "TRADE_SUCCESS".equals(res.get("trade_status")))) {
                rentOrderService.rentOrderPaySuccess(payNo, res.get("trade_no"));
            }
        } catch (Exception e) {
            log.error("支付异常!", e);
        }
        return "success";
    }

    @ApiOperation("租赁套餐续租支付宝支付通知")
    @PostMapping("/ali/pay/relet/{agentId}/{reletOrderId}")
    public String aliReletPayNotify(@PathVariable("agentId") String agentId, @PathVariable("reletOrderId") Integer reletOrderId, HttpServletRequest request) {
        try {
            log.info("租赁套餐续租支付宝异步回调：{}", request.getRequestURI());
            log.info("租赁套餐续租支付宝异步回调：{}", request.getParameterMap());
            AgentInfo agentInfo = agentCacheService.getAgent(agentId);
            LocalMapUtil.setAgentInfo(agentInfo);
            Map<String, String> res = AliPayUtil.getRequestParam(request, agentInfo.getAliPayPublicCertPath());
            String payNo = res.get("out_trade_no");
            String key = SpringContextUtil.getAppName().toUpperCase() + ":BIKE:RENT:PAY:RELET:NOTIFY:" + payNo;
            if (redisService.hasKey(key)) {
                throw new BadResponseException("租赁套餐续租订单重复响应：" + payNo);
            }
            redisService.set(key, payNo, 60 * 10);
            if (res.size() > 0 && ("TRADE_FINISHED".equals(res.get("trade_status")) || "TRADE_SUCCESS".equals(res.get("trade_status")))) {
                rentOrderService.reletOrderSuccess(payNo, res.get("trade_no"), reletOrderId);
            }
        } catch (Exception e) {
            log.error("支付异常!", e);
        }
        return "success";
    }

    @ApiOperation("租赁退款")
    @PostMapping("/wx/rent/refund/{agentId}")
    public Map<String, String> refund(@PathVariable("agentId") String agentId, HttpServletRequest request) {
        try {
            AgentInfo agentInfo = agentCacheService.getAgent(agentId);
            LocalMapUtil.setAgentInfo(agentInfo);

            JSONObject res = JSONObject.parseObject(WxPayUtil.parseNotify(request, agentInfo.getWxApiKey3(), agentInfo.getWxPlatformCertPath()));
            log.info("租赁微信退款结果通知:{}", JSONObject.toJSONString(res));
            String refundNo = res.getString("out_refund_no");
            String key = SpringContextUtil.getAppName().toUpperCase() + ":BIKE:RENT:REFUND:NOTIFY:" + refundNo;
            if (redisService.hasKey(key)) {
                log.info("租赁微信支付结果通知:{} 订单重复响应", refundNo);
                throw new BadResponseException("订单重复响应：" + refundNo);
            }
            redisService.set(key, refundNo, 60 * 10);

            EbRefundInfo ebRefundInfo = refundInfoService.getOne(new LambdaQueryWrapper<EbRefundInfo>()
                    .eq(EbRefundInfo::getRefundNo,refundNo)
                    .last("limit 0,1"));
            Assert.notNull(ebRefundInfo,"退款记录不存在!");
            ebRefundInfo.setChannelNo(res.getString("refund_id"));
            rentOrderService.rentRefundSuccess(ebRefundInfo, res.getString("out_trade_no"));
        }catch (Exception e){
            log.error("支付结果通知异常", e);
        }
        Map<String, String> map = new HashMap<>(12);
        map.put("code", "SUCCESS");
        map.put("message", "成功");
        return map;
    }
}
